package org.zjx.core;

import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.zjx.action.IAction;
import org.zjx.action.StrategyAction;
import org.zjx.manager.ActivationManager;
import org.zjx.operation.OperationExecutor;
import org.zjx.operation.WindowOperation;
import org.zjx.state.StateManager;

import java.awt.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

@Slf4j
public abstract class AbstractWindow implements IWindow, Runnable {
    private final String id;
    @Setter
    protected WinDef.HWND hwnd;
    private final StateManager stateManager;
    protected final OperationExecutor executor;
    protected final BlockingQueue<IAction> actionQueue;
    private final AtomicBoolean running = new AtomicBoolean(false);
    private final AtomicBoolean shutdownRequested = new AtomicBoolean(false);
    private final AtomicReference<Thread> executionThreadRef = new AtomicReference<>();
    private final CountDownLatch terminationLatch = new CountDownLatch(1);

    private final ExecutorService actionExecutor;


    public AbstractWindow(WinDef.HWND hwnd, OperationExecutor executor) {
        this(hwnd, executor, 50); // 默认队列大小
    }

    public AbstractWindow(WinDef.HWND hwnd, OperationExecutor executor, int queueCapacity) {
        if (hwnd == null) {
            throw new IllegalArgumentException("窗口句柄不能为空");
        }
        this.id = "game-" + System.currentTimeMillis();
        this.hwnd = hwnd;
        this.executor = executor;
        this.stateManager = new StateManager();
        this.actionQueue = new LinkedBlockingQueue<>(queueCapacity);
        this.actionExecutor = Executors.newSingleThreadExecutor(r -> {
            Thread t = new Thread(r, "窗口命令执行器-" + getId());
            t.setDaemon(true);
            return t;
        });

        start();
    }


    @Override
    public String getId() {
        return id;
    }

    @Override
    public WinDef.HWND getHwnd() {
        return hwnd;
    }

    @Override
    public String getTitle() {
        char[] buffer = new char[1024];
        int length = User32.INSTANCE.GetWindowText(hwnd, buffer, buffer.length);
        return length > 0 ? new String(buffer, 0, length) : "Unknown";
    }

    @Override
    public int getProcessId() {
        return 0;
    }

    @Override
    public boolean isExists() {
        return User32.INSTANCE.IsWindow(hwnd);
    }

    @Override
    public Rectangle getBounds() {
        WinDef.RECT rect = new WinDef.RECT();
        User32.INSTANCE.GetWindowRect(hwnd, rect);
        return new Rectangle(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
    }

    @Override
    public void activate() {
        User32.INSTANCE.SetForegroundWindow(hwnd);
    }

    @Override
    public boolean isActive() {
        return ActivationManager.getCurrentActiveWindow() == this;
    }

    @Override
    public boolean waitForActive(long timeoutMs) {
        long endTime = System.currentTimeMillis() + timeoutMs;
        while (System.currentTimeMillis() < endTime) {
            if (isActive()) return true;
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                break;
            }
        }
        return false;
    }

    @Override
    public void close() {

    }

    @Override
    public StateManager getState() {
        return stateManager;
    }

    @Override
    public void start() {
        if (running.compareAndSet(false, true)) {
            Thread thread = new Thread(this, "窗口线程-" + getId());
            thread.setDaemon(true);
            thread.start();
            log.info("[窗口] {} 创建并启动", getId());
        }
    }

    @Override
    public void shutdown() {
        if (shutdownRequested.compareAndSet(false, true)) {
            log.info("[窗口] 停止: {}", getId());

            running.set(false);
            actionQueue.clear();

            Thread executionThread = executionThreadRef.get();
            if (executionThread != null && executionThread.isAlive()) {
                executionThread.interrupt();
            }

            actionExecutor.shutdown();
        }
    }

    @Override
    public boolean isRunning() {
        return running.get();
    }

    @Override
    public <T> T execute(WindowOperation<T> operation) {
        return operation.execute(executor);
    }

    @Override
    public OperationExecutor getExecutor() {
        return executor;
    }

    @Override
    public void run() {
        log.info("[窗口] {} 执行线程启动", getId());
        executionThreadRef.set(Thread.currentThread());

        try {
            while (running.get() && !shutdownRequested.get()) {
                try {
                    if (!isValid()) {
                        log.warn("[窗口] {} 已失效，停止处理命令", getId());
                        break;
                    }

                    IAction action = actionQueue.poll(100, TimeUnit.MILLISECONDS);
                    if (action != null) {
                        executeAction(action);
                    } else {
                        // 无命令执行策略
                        submitStrategyAction();
                    }

                } catch (InterruptedException e) {
                    if (shutdownRequested.get()) {
                        log.info("[窗口] {} 执行线程在关闭期间被中断", getId());
                        break;
                    }
                    log.warn("[窗口] {} 执行线程意外中断", getId());
                    Thread.currentThread().interrupt();
                    break;
                } catch (Exception e) {
                    log.error("[窗口] {} 执行线程错误: {}", getId(), e.getMessage(), e);
                }
            }
        } finally {
            running.set(false);
            terminationLatch.countDown();
            log.info("[窗口] {} 执行线程停止", getId());
        }
    }

    private void submitStrategyAction() {
        try {
            // 检查命令队列是否为空
            if (actionQueue.isEmpty()) {
                // 队列为空，提交策略命令
                log.info("[GameWindow] 检测到命令队列为空，准备提交策略命令: {}", getId());

                StrategyAction strategyAction = new StrategyAction(this);
                submitAction(strategyAction);
                log.debug("[GameWindow] 策略命令已提交: {}", getId());
            }
        } catch (Exception e) {
            log.error("[GameWindow] 检查并提交策略命令失败: {}", getId(), e);
        }
    }

    @Override
    public CompletableFuture<Boolean> submitAction(IAction action) {
        if (action == null) {
            log.error("[窗口] 不能提交空命令到: {}", getId());
            return CompletableFuture.completedFuture(false);
        }

        if (!running.get() || shutdownRequested.get()) {
            log.error("[窗口] 不能向已停止的窗口提交命令: {}", getId());
            return CompletableFuture.completedFuture(false);
        }

        if (!isValid()) {
            log.error("[窗口] 窗口已失效，不能提交命令: {}", getId());
            return CompletableFuture.completedFuture(false);
        }

        boolean offered = actionQueue.offer(action);
        if (!offered) {
            log.warn("[窗口] 命令队列已满，丢弃命令: {} -> {}", action.getActionName(), getId());
            return CompletableFuture.completedFuture(false);
        }

        log.debug("[窗口] 命令 {} 提交到 {}",action.getActionName(), getId());

        // 返回异步结果
        return CompletableFuture.supplyAsync(() -> {
            // 命令会在主循环中执行，这里只是跟踪提交状态
            return true;
        }, actionExecutor);
    }


    @Override
    public void executeAction(IAction Action) {
        if (Action == null) return;

        String ActionName = Action.getActionName();
        log.debug("[窗口] {} 开始执行命令: {}", getId(), ActionName);

        long startTime = System.currentTimeMillis();
        boolean success;

        try {
            success = Action.execute();
            long duration = System.currentTimeMillis() - startTime;

            if (success) {
                log.debug("[窗口] {} 完成命令: {} 耗时 {}ms", getId(), ActionName, duration);
            } else {
                log.warn("[窗口] {} 命令执行失败: {} 耗时 {}ms", getId(), ActionName, duration);
            }

        } catch (InterruptedException e) {
            log.warn("[窗口] {} 命令执行被中断: {}", getId(), ActionName);
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            long duration = System.currentTimeMillis() - startTime;
            log.error("[窗口] {} 执行命令错误: {} 耗时 {}ms", getId(), ActionName, duration, e);
        }
    }

    @Override
    public boolean isValid() {
        return isExists() && running.get();
    }

    @Override
    public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
        return terminationLatch.await(timeout, unit) &&
                actionExecutor.awaitTermination(timeout, unit);
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            if (running.get()) {
                log.warn("[窗口] {} 在finalize时仍在运行，执行紧急关闭", getId());
                shutdown();
            }
        } finally {
            super.finalize();
        }
    }
}
